	package aden.HexEnv;
	
	import aden.HexEnv.HexEnvTile;
	import aden.HexEnv.HexEnvWorld;
	import aden.Generic.GenGeomLine;
	import aden.Generic.GenWorld;
	import aden.Generic.GenMain;
	
	public class HexEnvWorld extends GenWorld
	{
	    public HexEnvView GetHexEnvView() {return (HexEnvView)(mMain.GetView());}
	    
	    protected HexEnvTile mBoard[][];  
	    protected HexEnvTile mNextBoard[][];  
	    protected int          mHeight;
	    protected int          mWidth;
	
	    public HexEnvWorld(GenMain inMain,
	                       int inWidth,
	                         int inHeight)
	    {
	        super(inMain);
	        mHeight = inHeight;
	        mWidth  = inWidth;
	        mBoard = new HexEnvTile[mWidth][mHeight];
	        mNextBoard = new HexEnvTile[mWidth][mHeight];
	    }
	
	    public int GetHeight()
	    {
	        return mHeight;
	    }
	    
	    public int GetWidth()
	    {
	        return mWidth;
	    }
	    
	    public HexEnvTile GetTile(int inX,
	                         int inY)
	    {
	        return mBoard[inX][inY];
	    }
	
	    public HexEnvTile GetNextTile(int inX,
	            int inY)
	    {
	        return mNextBoard[inX][inY];
	    }
	
	    public static final int Neighbour_E = 0;
	    public static final int Neighbour_NE = 1;
	    public static final int Neighbour_NW = 2;
	    public static final int Neighbour_W = 3;
	    public static final int Neighbour_SW = 4;
	    public static final int Neighbour_SE = 5;
	    public static final int Neighbour_Undefined = 6;
	    
	    private static int sIterNeighboursPosX[];
	    private static int sIterNeighboursPosY[];
	        
	    public int GetNeighbourX(int inNeighbour,int inX,int inY)
	    {
	        if (sIterNeighboursPosX == null)
	        {
	        	sIterNeighboursPosX = new int[Neighbour_Undefined];
	        	sIterNeighboursPosY = new int[Neighbour_Undefined];
	        	
	        	sIterNeighboursPosX[Neighbour_E] = 1;
	        	sIterNeighboursPosY[Neighbour_E] = 0;
	        	sIterNeighboursPosX[Neighbour_NE] = 0;
	        	sIterNeighboursPosY[Neighbour_NE] = 1;
	        	sIterNeighboursPosX[Neighbour_NW] = -1;
	        	sIterNeighboursPosY[Neighbour_NW] = 1;
	        	sIterNeighboursPosX[Neighbour_W] = -1;
	        	sIterNeighboursPosY[Neighbour_W] = 0;
	        	sIterNeighboursPosX[Neighbour_SW] = -1;
	        	sIterNeighboursPosY[Neighbour_SW] = -1;
	        	sIterNeighboursPosX[Neighbour_SE] = 0;
	        	sIterNeighboursPosY[Neighbour_SE] = -1;
	
	        }
	    	int theX = inX + sIterNeighboursPosX[inNeighbour];
	    	if (inNeighbour != Neighbour_E &&
	    		inNeighbour != Neighbour_W &&
		    	inY % 2 != 0)
	    	{
	    		++theX;
	    	}
	    	return theX;
	    }
	
	    public int GetNeighbourY(int inNeighbour,int inX,int inY)
	    {
	    	return inY + sIterNeighboursPosY[inNeighbour];
	    }
	
	    public boolean Evolve()
	    {
	        // on initialize le mNextBoard
	        // ## a faire
	        return true;
	    }
	
	    static private float sVirtualGridForIterLine = 15;
	
	    public class HexEnvIterTile
	    {
	        private boolean       mIsNotDone;
	        private HexEnvWorld mWorld;
	        private int           mX;
	        private int           mY; // inutile
	        
	        
	        private int           mXmin; // in neighbour mode: centerx
	        private int           mYmin; // in neighbour mode: centery
	
	        // for box mode
	        private int           mXmax;
	        private int           mYmax;
	        
	        // for neighbours
	        private int mRange;
	        private int mIndice;
	        private int mNeighbourFace;
	        
	        private GenGeomLine mLine;
	        
	        public static final int Mode_BOX = 0;
	        public static final int Mode_NEIGHBOURS = 1;
	        public static final int Mode_LINE = 2;
	        public static final int Mode_Undefined = 3;
	
	        private int mMode;
	        
	        public HexEnvIterTile()
	        {
	            mIsNotDone = false;
	        }
	
	        public boolean Begin(HexEnvWorld inWorld)
	        {
	            mWorld = inWorld;
	            mXmin = 0;
	            mYmin = 0;
	            mXmax = inWorld.mHeight - 1;
	            mYmax = inWorld.mWidth - 1;
	
	            mX = mXmin;
	            mY = mYmin;
	            mIsNotDone = true;
	            mMode = Mode_BOX;
	            return true;
	        }
	
	        public boolean Begin(HexEnvWorld inWorld,
	                             int inXmin,
	                             int inYmin,
	                             int inXmax,
	                             int inYmax)
	        {
	            mWorld = inWorld;
	            mXmin = inXmin;
	            mYmin = inYmin;
	            mXmax = inXmax;
	            mYmax = inYmax;
	
	            mX = mXmin;
	            mY = mYmin;
	            mIsNotDone = true;
	            mMode = Mode_BOX;
	            return true;
	        }
	
	        
	        public boolean BeginLine(HexEnvWorld inWorld,
	        		int inX1,
	        		int inY1,
	        		int inX2,
	        		int inY2,
	        		boolean inIsFrom1To2)
	        {
	        	mWorld = inWorld;
	
	        	if (inIsFrom1To2)
	        	{
	        		mXmin = inX1;
	        		mYmin = inY1;
	        		mXmax = inX2;
	        		mYmax = inY2;
	        	}
	        	else
	        	{
	        		mXmin = inX2;
	        		mYmin = inY2;
	        		mXmax = inX1;
	        		mYmax = inY1;        		
	        	}
	    		mX = inX1;
	    		mY = inY1;
	//        	
	//    		mLine = new GenGeomLine(HexEnvView.GetHexCenterX(inX1,inY1,0,sVirtualGridForIterLine,0),
	//    				                HexEnvView.GetHexCenterY(inX1,inY1,0,sVirtualGridForIterLine,0),
	//    				                HexEnvView.GetHexCenterX(inX2,inY2,0,sVirtualGridForIterLine,0),
	//    				                HexEnvView.GetHexCenterY(inX2,inY2,0,sVirtualGridForIterLine,0));
	//    		
	        	mIsNotDone = true;
	        	mMode = Mode_LINE;
	        	return true;
	        }
	
	        public boolean BeginNeighbours(HexEnvWorld inWorld,
	        		int inXCenter,
	        		int inYCenter,
	        		int inRange)
	        {
	        	mWorld = inWorld;
	        	mXmin = inXCenter;
	        	mYmin = inYCenter;
	        	
	        	mRange = inRange;
	        	mIsNotDone = true;
	        	mIndice = 0;
	        	mMode = Mode_NEIGHBOURS;
	        	mNeighbourFace = Neighbour_E;
	        	mY = mYmin;
	        	mX = mXmin + mRange;
	    		if (0 <= mX && mX < mWidth &&
	        		    0 <= mY && mY < mHeight)
	        	{
	        		return true;
	        	}
	
	        	return NextNeighbour();
	        }
	
	        public boolean IsNotDone()
	        {
	            return mIsNotDone;
	        }
	
	        public HexEnvTile Content()
	        {
	            return mWorld.mBoard[mX][mY];
	        }
	
	        public int GetX()
	        {
	            return mX;
	        }
	        
	        public int GetY()
	        {
	            return mY;
	        }
	        
	        public int GetNeighbourIndex()
	        {
	        	return mIndice + mNeighbourFace * mRange;
	        }
	        
	        private boolean NextNeighbour()
	        {
	        	while (true)
	        	{        		
	    			++mIndice;
	    			int theNextNeighbourFace = mNeighbourFace;
	    			if (mIndice == mRange)
	    			{
	    				mIndice = 0;
	    				theNextNeighbourFace = mNeighbourFace + 1;
	    				if (theNextNeighbourFace == Neighbour_Undefined)
	    				{
	    					mIsNotDone = false;
	            			return false;
	    				}
	    			}
	        		int theNextX = GetNeighbourX((mNeighbourFace + Neighbour_NW) % 6,mX,mY);
	        		int theNextY = GetNeighbourY((mNeighbourFace + Neighbour_NW) % 6,mX,mY);
	        		mNeighbourFace = theNextNeighbourFace;
	        		mX = theNextX;
	        		mY = theNextY;
	
	        		if (0 <= mX && mX < mWidth &&
	        		    0 <= mY && mY < mHeight)
	        		{
	        			return true;
	        		}
	        	}
	        }
	
	        public boolean Next()
	        {
	            if (mIsNotDone)
	            {
	            	if (mMode == Mode_NEIGHBOURS)
	            	{
	            		NextNeighbour();
	            	}
	            	else if (mMode == Mode_LINE)
	            	{
	            		if (mX == mXmax &&
	            			mY == mYmax)
	            		{
	            			mIsNotDone = false;
	            			return false;
	            		}
	            		
	            		// we are looking for the neighbours and keep only the closest to (XMax,YMax) as the next tile.
	            		
	            		int theNeighbour, theClosestNeighbour = -1;
	            		int theX, theY;
	            		
	            		int theMinSqrDist = (mXmax - mX) * (mXmax - mX) + (mYmax - mY) * (mYmax - mY);
	            		for (theNeighbour = 0;
	            			 theNeighbour < Neighbour_Undefined;
	            			 ++theNeighbour)
	            		{
	                		theX = GetNeighbourX(theNeighbour,mX,mY);
	                	    theY = GetNeighbourY(theNeighbour,mX,mY);
		            		int theSqrDist = (mXmax - theX) * (mXmax - theX) + (mYmax - theY) * (mYmax - theY);
		            		if (theSqrDist < theMinSqrDist)
		            		{
		            			theMinSqrDist = theSqrDist;
		            			theClosestNeighbour = theNeighbour;
		            		}
	            		}           		
	            		
	            		if (theClosestNeighbour == -1)
	            		{
	            			mIsNotDone = false;
	            			return false;	            			
	            		}
	            		
                		mX = GetNeighbourX(theClosestNeighbour,mX,mY);
                	    mY = GetNeighbourY(theClosestNeighbour,mX,mY);
                	    
	//            		
	//            		int theNeighbour;
	//            		boolean theIsAbove = mLine.IsPointAbove(HexEnvView.GetHexTileOffsetX(0,sVirtualGridForIterLine),
	//            				                             HexEnvView.GetHexTileOffsetY(0,sVirtualGridForIterLine));
	//            		for (theNeighbour = 1;
	//            			 theNeighbour < Neighbour_Undefined;
	//            			 ++theNeighbour)
	//            		{
	//            			if (theIsAbove != mLine.IsPointAbove(HexEnvView.GetHexTileOffsetX(theNeighbour,sVirtualGridForIterLine),
	//	                                                       HexEnvView.GetHexTileOffsetY(theNeighbour,sVirtualGridForIterLine)))
	//            			{
	//            				break;
	//            			}
	//            		}
	//            		theNeighbour = theNeighbour % Neighbour_Undefined;
	//            		
	//            		mX = GetNeighbourX(theNeighbour,mX,mY);
	//            		mY = GetNeighbourY(theNeighbour,mX,mY);
	            	}
	            	else if (mMode == Mode_BOX)
	            	{
	            		++mX;
	            		if (mXmax < mX)
	            		{
	            			mX = mXmin;
	            			++mY;
	            			if (mYmax < mY)
	            			{
	            				mIsNotDone = false;
	            			}
	            		}
	            	}
	            }
	            return mIsNotDone;
	        }
	    }
	    
	    public boolean Autogenerate()
	    {
	        return true;
	    }
	    
	}
	
	
